>>>>>>>>>>>>>>>>  CVBasic user's manual  <<<<<<<<<<<<<<<<

                     by Oscar Toledo G.
              (c) Copyright 2024 Oscar Toledo G.
                    http://nanochess.org/

First developed: Feb/27/2024
Last revision: Aug/25/2025


>>>>>>>>>>>>>>  Legal notice

This software is provided 'as-is', without any express or implied warranty. 
In no event will the author be held liable for any damages or loss arising 
from the use of this software.

It is prohibited to modify, decompile, disassemble or reverse engineer this 
software.

All trademarks are property of their respective owners.


>>>>>>>>>>>>>>  Changes in this version

v0.9.0 Aug/26/2025  o Added support for NES/Famicom using --nes
                    o MSX: Added support for Konami mapper using -konami
                    o Solved bug in DEF FN precedence inside expressions.
                    o Solved bug in > operator with 16-bit variable.
                    o NABU: Solved bug where compilation would warn of both
                      sound chips.
                    o TI-99/4A: Corrected bug in CHR$ and DEFINE VRAM READ.
                    o TI-99/4A: Solved bugs doing operations with 8-bit
                      variables and 16-bit values.
                    o TI-99/4A: Solved bug in multiplication by 1.
                    o TI-99/4A: Solved bug in SELECT CASE.
                    o TI-99/4A: Solved bug in DEFINE COLOR PLETTER.
                    o TI-99/4A: Optimizes more operations with constants.
                    o TI-99/4A: Added more optimization using register labeling,
                      saves many bytes, and speeds up.

v0.8.0 Apr/26/2025  o Added support for Sega Master System using --sms
                    o Added support for VDP.STATUS (for reading VDP status)
                    o Added SELECT CASE / END SELECT
                    o Added support for CHR$ in PRINT (for portable printing of
                      arbitrary characters in the current cursor position)
                    o Added SCROLL statement for Sega Master System.
                    o Added BORDER flags for Sega Master System.
                    o Added PALETTE statement for Sega Master System.
                    o Adapted BITMAP, SCREEN, and SPRITE for Sega Master System.
                    o Optimizes code using directly DI/EI instructions in Z80
                      platforms if possible.

v0.7.1 Oct/15/2024  o Added support for NABU PC using --nabu (with -cpm option)
                    o Added support for USR/CALL with up to 5 arguments (only Z80)
                    o Added DEFINE VRAM READ to read VRAM.
                    o Added new example brinquitos.bas
                    o Added new example vramcopy.bas
                    o Optimizes division by 16 (Z80).

v0.7.0 Sep/03/2024  o Added support for Texas Instruments TI-99/4A --ti994a
                      (contributed by tursilion)
                    o Added suppprt for Hanimex/Soundic Pencil II using --pencil
                    o Added support for Tatung Einstein using --einstein
                    o Added support for Casio PV-2000 using --pv2000
                    o Added automatic protection code for mixer register (AY-3-8910)

v0.6.0 Aug/07/2024  o Added support for Creativision / Dick Smith's Wizzard (6502
                      processors!) using --creativision
                    o Added support for Sord M5 computers using --sord
                    o Added support for Memotech MTX computers using --memotech and -cpm
                    o Added VDP() command to set VDP registers.
                    o Added support for 16K of RAM in MSX using -ram16
                    o Optimizes 8-bit division by power of two.
                    o Optimizes pointer subtraction (VARPTR a(0) - VARPTR a(5))
                    o Added peephole optimizer for Z80 backend.

v0.5.1 Jun/25/2024  o Added SIGNED and UNSIGNED keywords to tag variables
                      (both 8-bit and 16-bit) and enable signed comparisons,
                      division, and modulo.
                    o The MSX target now supports 0-9, - and = for CONT1.KEY.
                    o Added new target Spectravideo SVI-318/328 (using
                      option --svi)
                    o Better assembler output for DATA.
                    o Optimized addition by 256.
                    o Optimized byte variable multiplied by 256.
                    o Optimized extra RET generated when using RETURN.
                    o Optimized use of Z flag.
                    o Optimized AND/OR/XOR of constant with 8-bit variable.
                    o Optimized code generation to avoid unnecessary PUSH/POP.
                    o More powerful optimization taking note of register usage.
                    o Reports open control block at end of procedure/program.
                    o Solved bug of undetected unfinished loop at global level.
                    o Solved bug of joystick not working in SC3000.
                    o Solved bug when subtracting two pointers (VARPTR)
                    o Solved bug where error would indicate wrong file (INCLUDE)
                    o Solved bug where Megacart didn't worked with --sgm, nor
                      the NTSC variable.

>>>>>>>>>>>>>>. Description

CVBasic is an integer BASIC compiler for Colecovision, MSX, Sega SG1000, Spectravideo SVI-318/328, Sord M5, Memotech MTX, Creativision, Soundic Pencil II, Tatung Einstein, Casio PV-2000, TI-99/4A, NABU PC, Sega Master System, and NES/Famicom.

It works as a cross-compiler over a PC and generates assembler code that can be processed by Gasm80.

Platforms requirements:
  o PC with Windows XP or better.
  o macOS X 10.6 or better (universal 32/64-bit binary)
  o Linux.

The current limitations are:
  o ASM cannot be used inside DEF FN.
  o Using PRINT for numbers always show numbers as unsigned from 0 to 65535.

Usage:
  
  cvbasic in.bas output.asm
  cvbasic --sg1000 in.bas output.asm
  cvbasic --msx in.bas output.asm
  cvbasic --msx -ram16 in.bas output.asm
  cvbasic --sgm in.bas output.asm
  cvbasic --svi in.bas output.asm
  cvbasic --sord in.bas output.asm
  cvbasic --memotech in.bas output.asm
  cvbasic --memotech -cpm in.bas output.asm
  cvbasic --creativision in.bas output.asm
  cvbasic --pencil in.bas output.asm
  cvbasic --einstein in.bas output.asm
  cvbasic --pv2000 in.bas output.asm
  cvbasic --ti994a in.bas output.a99
  cvbasic --nabu in.bas output.asm
  cvbasic --sms in.bas output.asm
  cvbasic --nes in.bas output.asm

The following modules are automatically included as the prologue and epilogue of your generated code and they set important variables and helper code:

  cvbasic_prologue.asm
  cvbasic_epilogue.asm

Afterwards, you should assemble your program using the included Gasm80 assembler.

  gasm80 output.asm -o output.rom

For Memotech you should use the .run extension or .com extension (if used -cpm option)

The Creativision port uses cvbasic_6502_prologue.asm and cvbasic_6502_epilogue.asm

The TI-99/4A port uses cvbasic_9900_prologue.asm and cvbasic_9900_epilogue.asm and it should be assembled using xdt tools. (xas99 with the -R option)

The NES/Famicom port uses cvbasic_nes_prologue.asm and cvbasic_nes_epilogue.asm

The NABU port requires the gasm output file to be named 000001.nabu and you should ZIP it to test it with MAME. If you use the -cpm option you can use any .com file name.

And finally, you can test the generated output.rom file using CoolCV, blueMSX, openMSX, or a Flash cartridge for real hardware.


>>>>>>>>>>>>>>  Supporting the developer

If you find CVBasic useful, please show your appreciation making a donation via Paypal ($9 USD suggested) to b-i+y-u+b-i (at) gmail.com

If you find a bug, please report to same email and I'll try to look into it. Because lack of time I cannot guarantee it will be corrected.


>>>>>>>>>>>>>>  CVBasic language specification
  
Execution starts at the first line of the BASIC program.

Syntax per line:
  [label:] statement[:statement] [' comment]

  MAIN:    PRINT "HELLO"  ' Prints hello
  
Multiple statements are allowed, but these must be separated by colons.

Variables are created simply by being used.

Labels are created simply by being used.

You can use a period before a label name to mark a local label. The local label's real name is based on the most recent global label (any label that doesn't start with a period) concatenated with the local label.

A variable name starts with a letter or # and is followed by letters, numbers, or the underscore character.

Variables and arrays (see DIM) can be 8-bit or 16-bit. Variables and arrays are 8-bit, if you want a 16-bit variable or array use # as the initial character of the variable's name.

    x
    y
    #score
    
Notice that if you use the # prefix you should use it everywhere in your program. Variables with the same name but without the # prefix are treated as different 8-bit variables.
    
All variables are initialized with the value 0 (zero) when they are created.

The following statements are available:

  REM comment      
  ' comment
  
     Everything between REM and the end of the line is treated by the compiler
     as a comment.

  SIGNED name[,name]
  
     Indicates that names are signed variables/arrays.

     This allows to use of signed comparisons, division, and modulo. Notice this
     adds extra code to extend sign on operations, and do signed comparisons.

     Typically you can develop your programs without using this keyword, but it's
     available if you really need it.

  UNSIGNED name[,name]
  
     Indicates that names are unsigned variables/arrays.

     This is the default behavior of variables/arrays in CVBasic.

  CONST [name]=[constant expression]
  
     Assign a name to a constant expression. The compiler will replace all
     instances of this name, in all expressions, with the number. These names
     have priority over variable names.

     This is like a compiler directive, it doesn't generate code and it can
     appear anywhere in the program but it will be treated as a constant from
     the point of appearance onwards.

     Constants that start with the # prefix are treated as 16-bit numbers, and
     if this isn't present then the constant will be treated as an 8-bit number.

     Constants can be passed-in to CVBasic via the command-line:

       cvbasic -DMYCONST=123 in.bas output.asm
       cvbasic -D#MYBIGCONST=12345 in.bas output.asm
  
  GOTO label        
  
     Go to label.

     It's erroneous to jump from inside a PROCEDURE to outside of the same
     PROCEDURE. 

  GOSUB label       
  
     Go to a subroutine located at label (must be a PROCEDURE).
  
  label: PROCEDURE
  [code for subroutine]
  END
  
     Create a PROCEDURE callable by GOSUB.

     It's important that PROCEDURE is on the same line as the label.

     END implies an automatic RETURN.

  RETURN            
  
     Return from subroutine (PROCEDURE). Also can be used for an early return from a
     PROCEDURE.

  FOR A=start TO end [STEP increment]
  NEXT     ' Also supported NEXT A
  
  FOR A=1 TO 5 ' Loop
    [Variable A will contain 1,2,3,4,5]
  NEXT A
  
  FOR A=1 TO 5 STEP 2
    [Variable A will contain 1, 3, 5]
  NEXT A
  
  FOR A=5 TO 1 STEP -2
    [Variable A will contain 5, 3, 1]
  NEXT A
  
     Looping statement.
     
     The start, end, and step expressions can be complex expressions, instead of
     only constants or variables.

     Notice that you can only use regular variables for the loop variable, not
     array variables. There is a small quirk if you're using an 8-bit variable
     and the TO expression is pretty complex and reaches 0 or 255, the loop can
     be infinite.
     
  WHILE expr:[statement]:WEND
  WHILE expr
  [statement]
  WEND
  
     Looping statement that keeps looping as long as the expression evaluates
     to non-zero.
     
  DO WHILE expr:[statement]:LOOP
  DO WHILE expr
    [statement]
  LOOP

  DO UNTIL expr:[statement]:LOOP
  DO UNTIL expr
    [statement]
  LOOP
  
  DO:[statement]:LOOP WHILE expr
  DO
    [statement]
  LOOP WHILE expr
  
  DO:[statement]:LOOP UNTIL expr
  DO
    [statement]
  LOOP UNTIL expr
  
     Looping statements that keep looping WHILE expression evaluates to
     non-zero, or UNTIL expression evaluates to non-zero.

  EXIT FOR
    
     Exits current FOR loop. It jumps directly to the line that follows NEXT.

  EXIT WHILE
  
     Exits current WHILE loop. It jumps directly to the line that follows WEND.
     
  EXIT DO
     
     Exits current DO loop. It jumps directly to the line that follows LOOP.

  IF expr GOTO [label]
  IF expr THEN [statement]
  IF expr THEN [statement] ELSE [statement]

  IF expr THEN
    [statement]
  END IF
  
  IF expr THEN
    [statement]
  ELSE
    [statement]
  END IF
  
  IF expr THEN
    [statement]
  ELSEIF expr THEN
    [statement]
  END IF

  IF expr THEN
    [statement]
  ELSEIF expr THEN
    [statement]
  ELSE
    [statement]
  END IF

     Decision statement. The first statement is taken if the expression result
     is non-zero.


  ON expr GOTO [label],[label],[label]
  ON expr GOTO [label],,[label]
  ON expr GOTO ,,[label]
  ON expr GOSUB [label],[label],[label]
  ON expr GOSUB [label],,[label]
  ON expr GOSUB ,,[label]
  ON expr FAST GOTO
  ON expr FAST GOSUB

     Decision statement

     The expression is evaluated and if the result is zero, the first label
     is taken, if the result is one, the second label is taken, and
     successively up to any number of labels.

     If GOSUB is used then you must make sure that each label is linked to
     a PROCEDURE.

     If an option has no label or if the expression exceeds the number of
     labels, the execution flow continues with the following statement
     after ON.

     This statement can be made faster in execution using the FAST modifier,
     it will avoid checking boundaries, but if your list of labels doesn't cover
     the full expression range then your PROGRAM WILL CRASH.

  SELECT CASE expr
     CASE 1
       [statement]
     CASE 2 TO 4
       [statement]
     CASE ELSE
       [statement]
  END SELECT

     It evaluates the expression, and selects the statements to execute from the
     CASE statements. CASE ELSE should be the last statement if it is required to
     handle non-specified values. You can exit using EXIT SELECT.

  ON FRAME GOSUB label
  
     On each video frame interrupt, the CVBasic core will call the indicated
     PROCEDURE.

     This doesn't generate any code and should only appear once in your program.
     Also, it’s important to keep in mind this procedure could be called even
     before your initialization routines are executed.

     The only valid assumption is that every single variable is zero after
     booting. It's your responsibility that the code doesn't take too long to
     execute, otherwise video frame interrupts will accumulate, and your memory
     stack will overflow.

     If you are using bank-switching the procedure should be located in bank 0
     (this is after BANK ROM and before any BANK number statement).

  POKE address,data
  
     Poke memory with data.

  VPOKE address,data

     Poke VRAM with data.

     For Sega Master System:

     All the VRAM $0000-$3fff can be used for tiles. Each 8x8 tile uses 32 bytes.
     Each 8 bytes cover a color bit from least significant bit to most significant
     bit.

     However the area $3800-$3dff contains the screen pattern data. The even bytes
     contain the pattern number, and the odd bytes contain the bit 8 of pattern
     number. See the SCREEN statement for further details on the flags.

     For NES/Famicom:

     Only the VRAM area $2000-$27ff can be accessed. By default the full screen is
     displayed from the area $2000-$23ff. The remaining is used when the SCROLL
     statement is used.

     Any write to VRAM (VPOKE, PRINT, SCREEN) is buffered, this means it doesn't
     happen immediately, but instead when the next vertical refresh happens on
     the screen. This also means there is a limit to how much data you can
     update in a single frame (typically around 96-128 bytes).
 
     The internal buffer can get filled (22 VPOKE or number digits from PRINT,
     12 strings PRINT, or 12 SCREEN lines), and it will trigger automatically a
     WAIT so it doesn't overflow.

     If you are writing more than 96-128 bytes per frame, you can use
     SCREEN DISABLE and SCREEN ENABLE.

     These are the palette assignment bytes for the main screen.          

	$23c0 = XX XX XX XX XX XX XX XX
	$23c8 = XX XX XX XX XX XX XX XX
	$23d0 = XX XX XX XX XX XX XX XX
	$23d8 = XX XX XX XX XX XX XX XX
	$23e0 = XX XX XX XX XX XX XX XX
	$23e8 = XX XX XX XX XX XX XX XX
	$23f0 = XX XX XX XX XX XX XX XX
	$23f8 = XX XX XX XX XX XX XX XX

     Where each byte covers a 4x4 area:

          2 cols  2 cols
         |-------|-------|
         |bit 1-0|bit 3-2| 2 rows
         |-------|-------|
         |bit 5-4|bit 7-6| 2 rows
         |-------|-------|


  WAIT
  
     Waits for the next frame interruption (1/60 of a second for NTSC or 1/50
     of a second for PAL)

  OPTION WARNINGS ON
  OPTION WARNINGS OFF

     Enable/disable the compilation warnings. Note that if you disable warnings
     at the end of your program, you won't have the list of non-used variables.

  OPTION EXPLICIT
  OPTION EXPLICIT ON
  OPTION EXPLICIT OFF

     Makes it mandatory to declare each variable with DIM before said variable
     can be used.

  DIM variable
  DIM variable[,variable]
  
     Declares a variable.
     
     Useful in combination with OPTION EXPLICIT.
     
  DIM var(size)
  
     Creates an array of data called 'var' of 'size' elements.
     Counting starts on zero, so DIM A(10) creates an array of 0 to 9.
     
     Also you can create arrays of 16-bits numbers, using the # sign
     as the first letter of the array name DIM #BIG(10)

     The array can be accessed as follows:
     
         A(1)=A(1)+5
         A(X)=A(Y)-2
         
     The DIM statement is like a directive, it doesn't generate code
     and it can appear anywhere in the program. The definition will start
     from the line of the DIM statement.

  RESTORE label

     Restores the READ pointer to start at the provided label.

  READ var
  READ BYTE var

     Reads a 16-bit value and puts it into the variable var.

     It can also read an 8-bit value and put it into the variable var.

     Make sure you pair correctly READ/DATA and READ BYTE/DATA BYTE,
     as otherwise the internal pointer will get desynchronized.

  DATA constant_expr[,constant_expr]
  DATA BYTE constant_expr[,constant_expr]
  DATA BYTE string
  DATA VARPTR a
  DATA VARPTR b(constant_expr)

     Defines 16-bit data to be stored in program memory, or also 8-bit data.

     DATA statements should be referred with a label starting with the # sign,
     and DATA BYTE statements should be referred to with a label not starting
     with the # sign.

     All data contained in DATA can also be accessed using the familiar
     array-indexing syntax, like this:
    
       FOR A=0 TO 4
       PRINT AT #TABLE(A),"Z"
       NEXT A
      
       #TABLE:
       DATA 21,42,63,84,105

  DEFINE CHAR char_num,total,label
  DEFINE CHAR char_num,total,VARPTR array(expr)
  DEFINE CHAR PLETTER char_num,total,label

     Loads graphics into VRAM. This sentence isn't used on NES/Famicom.

     "char_num" valid values are between 0 and 255.

     "total" valid values are between 1 and 256.

     It replaces the definitions for "char_num", "total" means the total number
     of characters to load, and "label" should point to a label containing
     BITMAP statements or DATA BYTE statements.

     Each character is an 8x8 pixel bitmap (represented as 8 BITMAP statements or
     8 constants in a DATA BYTE statement). For Sega Master System, this is 32
     constants in a DATA BYTE statement because the character definition includes
     color.

     Internally, CVBasic will replicate the data along the 3 display areas so
     the defined characters will appear on the whole screen when required.

     The VARPTR expression allows character definition from an offset inside an
     array so you can do animation easily.

     Use the optional argument PLETTER to indicate that the data is compressed
     with the Pletter compressor (TMSColor does the compression if you give the
     option -z)

     This sentence isn't supported for NES/Famicom.

  DEFINE COLOR char_num,total,label
  DEFINE COLOR char_num,total,VARPTR array(expr)
  DEFINE COLOR PLETTER char_num,total,label

     Loads color into VRAM. This sentence isn't used on Sega Master System nor
     NES/Famicom.

     "char_num" valid values are between 0 and 255.

     "total" valid values are between 1 and 256.

     It replaces the colors for "char_num", "total" means the total number
     of characters to load, and "label" should point to a label containing
     DATA BYTE statements.

     The color format is the standard one of the TMS9118 Video Display processor.
     Each character is composed of 8 rows, and each row can have a foreground
     color (upper nibble), and a background color (lower nibble).

     Internally, CVBasic will replicate the data along the 3 display areas so
     the defined characters will appear on the whole screen when required.

     The VARPTR expression allows color definition from an offset inside an
     array so you can do animation easily.

     Use the optional argument PLETTER to indicate that the data is compressed
     with the Pletter compressor (TMSColor does the compression if you give the
     option -z)

  DEFINE SPRITE sprite_num,total,label
  DEFINE SPRITE sprite_num,total,VARPTR array(expr)
  DEFINE SPRITE PLETTER sprite_num,total,label

     Loads sprites into VRAM. This sentence isn't used on NES/Famicom.

     "sprite_num" valid values are between 0 and 63 (127 for Sega Master System)

     "total" valid values are between 1 and 64 (128 for Sega Master System)

     It replaces the definitions for "sprite_num", "total" means the total number
     of sprites to load, and "label" should point to a label containing
     BITMAP or DATA BYTE statements with the sprite or sprites representation.

     Each sprite is 16x16 pixels (8x16 pixels for Sega Master System)

     The VARPTR expression allows sprite definition from an offset inside an
     array so you can do animation easily.

     Use the optional argument PLETTER to indicate that the data is compressed
     with the Pletter compressor (TMSColor does the compression if you give the
     option -z)

  DEFINE VRAM address,length,label
  DEFINE VRAM address,length,VARPTR array(expr)
  DEFINE VRAM PLETTER address,length,label

     Copies data from "label" into VRAM address "address". The total of bytes
     is defined by "length". This sentence isn't supported for NES/Famicom.

     The VARPTR expression allows choosing the origin from an offset inside an
     array so you can do animation easily.

     Use the optional argument PLETTER to indicate that the data is compressed
     with the Pletter compressor (TMSColor does the compression if you give the
     option -z)

  DEFINE VRAM READ address,length,label
  DEFINE VRAM READ address,length,VARPTR array(expr)

     Copies data from VRAM address "address" into "label". The total of bytes
     is defined by "length". This sentence isn't supported for NES/Famicom.

     The VARPTR expression allows choosing the origin from an offset inside an
     array.

  SOUND 0,[value 10 bits],[vol 0-15]
  SOUND 1,[value 10 bits],[vol 0-15]
  SOUND 2,[value 10 bits],[vol 0-15]
  SOUND 3,[control 4 bits],[vol 0-15]

     Allows to generate tones on the SN76489 sound processor. Volume values
     are 0 for no sound and 15 for the highest sound.


     The desired frequency value can be calculated this way:
   
         value = 3579545 / 32 / frequency

     Only a constant can be used as the first parameter of SOUND.

     The SN76489 allows four independent tones to be played at the same time.

     The first three channels are pure tones, and the fourth channel can be
     white noise (4<= control <= 7) or a tone with a special shape
     (0<= control <= 3)

     The frequency for the fourth channel is fixed (control is 0,1,2,4,5,6)
     or related to the frequency of the third channel (control is 3,7)

     If you use the music player, the SOUND capabilities are affected. Refer
     to the PLAY statement later for further information.

  SOUND 5,[VALUE 12 bits],[VOL 0-15]       Channel A
  SOUND 6,[VALUE 12 bits],[VOL 0-15]       Channel B
  SOUND 7,[VALUE 12 bits],[VOL 0-15]       Channel C
  SOUND 8,[VALUE 16 bits],[TYPE 0-15]      Volume envelope (frequency/shape)
  SOUND 9,[NOISE 5 bits],[MIX]      Noise and mix register ($b8 value by default)

     Allows to generate tones on the AY-3-8910 sound processor (MSX). Volume
     values are 0 for no sound and 15 for the highest sound.


     For channels A, B and C, if you use volume 16 the PSG will use the
     volume envelope (see SOUND 8)
    
     If you use the music player, the SOUND capabilities are affected. Refer
     to the PLAY statement later for further information.

     NOTE: USE ONLY VALUES $80-$BF FOR MIX BECAUSE ANY VALUE OUTSIDE THIS
           CAN BURN YOUR MSX HARDWARE.

  SOUND 10,[freq 16 bits],[vol 8 bits],[sweep 8 bits]
  SOUND 11,[freq 16 bits],[vol 8 bits],[sweep 8 bits]
  SOUND 12,[freq 16 bits],[linear counter]
  SOUND 14,[freq 16 bits],[vol 8 bits]
  SOUND 15,[setting 8 bits]

     Allows to generate tones on the NES/Famicom Audio Processing Unit (APU).

     For SOUND 10, 11, and 12, the frequency is a 11-bit number, and it has a
     duration. For starters you can add $0800 so you can make sure the tone
     will have the maximum duration (127 frames).

     For SOUND 14 the frequency is a 4-bit number, also you need to add $0800.

     The volume is a number from zero (silent) to fifteen (highest volume).

     Bit 4 means the volume is fixed (you probably will always use this by
     adding $10), else it uses an envelope decay (in combination with bit 5)

     Bits 7-6 indicate the duty cycle (0= 12.5%, 1= 25%, 2= 50%, 3= 75%)

     Sweep
       bit 7: 0=disable, 1=enable
       bit 6-4: Sweep update rate NTSC = 120hz / (n + 1), PAL = 96 hz / (n + 1)
       bit 3: 0=+increase, 1=-decrease
       bit 2-0: Sweep right shift amount (1 means one bit to right)
                until frequency value becomes zero.

     As SOUND 12 doesn't have a volume register, you should turn it on using
     SOUND 15, 15, and turn it off using SOUND 15, 11. Also the linear counter
     should have a non-zero value.

     Don't update the frequency if it is the same, or otherwise the output
     phase will reset and generate glitches in the audio output.


  SPRITE index,y,x,f,c    (All others)
  SPRITE index,y,x,f.     (SMS)
  SPRITE index,y,x,f,a    (NES/Famicom)

     The first parameter indicates the number of the sprite (0-31).

     Y contains the Y-coordinate for the top row of the sprite.
     The final result is one pixel below the expected pixel row, so you
     must subtract one.

     X contains the X-coordinate for the sprite (0-255)

     F contains the sprite frame. You must multiply the desired sprite
     definition (0-63) by 4 to show the right sprite. For Sega Master
     System the sprite frame is based on 8x8 blocks, so you need to use
     multiplies of 2 for each 8x16 sprite (0-254)

     C contains the color for the sprite (0-15). Alternatively, you can
     add the flag $80 (128 decimal) to displace the sprite by 32 pixels
     to the left. Allowing it to blend inside the screen from the left.

     The fourth argument (color) isn't used on Sega Master System, and
     it will generate an error from CVBasic if present.

     Sprites are updated on the vertical retrace.

     The Y-coordinate visible range for sprites is 240 to 255, and 0
     to 190. 240-254 allows the sprite to enter smoothly from the top,
     255 is the top pixel row of the screen, and 0-190 is the whole
     vertical range of the screen (190 is the bottom pixel row of
     the screen). Values 191-239 make the sprite invisible.

     Additionally, the value 208 for the Y-coordinate disables sprite
     processing starting on that very sprite. For example,
     SPRITE 0,$d0,0,0,0 forces sprites 1-31 to disappear even if active.

     NES/Famicom notes:

     y = Vertical position - 1 ($ff, $00 - $ee = scanline 0..239)
         To hide sprites use $f0 ($ef - $fe aren't displayed)
     x = Horizontal position.
     f = bit 7-1 = pattern number, bit 0 = pattern address ($0000 or $1000)
         An address of $0000 means the sprite will access the
         patterns 0-254, and an address of $1000 means the sprite
         will access the patterns 256-510.
     a = bit 7 = 1 = Vertical flip.
         bit 6 = 1 = Horizontal flip.
         bit 5 = 1 = Sprite behind background.
         bit 4-2 = Reserved.
         bit 1-0 = Sprite palette (0-3)

  SPRITE FLICKER ON
  SPRITE FLICKER OFF

     Turns sprite flicker on and off. By default, CVBasic will start with
     SPRITE FLICKER ON, this enables a code snippet that cycles sprites on
     the screen to circumvent the VDP limitation of 4 sprites in a row.

     If you turn it off, you can use the VDP limitation to make certain
     tricks, for example, putting black sprites for masking sprites in
     borders, overlapping sprites in different depths, or using the
     SPRITE 0,$d0,0,0,0 trick.

  OUT port,data

     It outputs "data" in the hardware port "port". Not available in 6502 targets.

  CLS

     Clears the screen. The screen buffer is filled with the value 32 (equivalent to ASCII space character).

     Also, it resets the internal cursor position to the top-left corner of the screen.

  PRINT [AT [expr]][,]["string"]

     Prints the given string at the current cursor coordinate (or
     selected via the AT value 0 to 767).

     The string is processed in ASCII, and CVBasic automatically
     defines the ASCII charset to be available at the start. You can
     redefine all the characters if required.

     If you want to use a character beyond the printable ones, you
     can use the inverted slash as an escape character (by example
     "\128\129")

     If you want to use double quotes inside a string you can
     escape it this way: \"

     Examples of positioning:

         PRINT AT 0,"A"    ' Upper-left corner
         PRINT AT 31,"A"   ' Upper-right corner
         PRINT AT 736,"A"  ' Bottom-left corner
         PRINT AT 767,"A"  ' Bottom-right corner

     NES/Famicom allows for a 32x30 screen area (960 characters),
     however, only the center area (28 rows) can be guaranteed
     to be visible.

  PRINT expr
  PRINT <const>expr     ' Right-aligned with zeroes to 'const' size.
  PRINT <.const>expr    ' Right-aligned with spaces to 'const' size.

     Displays expr as an ASCII number using characters between 48 and 57.

     Example:

        PRINT AT 8,"Score:",<5>#score,"00"

  PRINT CHR$(expr)

     Displays expr as a character on the video screen.

     Example:
 
        PRINT CHR$(65)

  BORDER color
  BORDER color,flags

     Select the border color. It can be a number from 0 to 15.

     The first argument isn't available for NES/Famicom, the small border around
     is always black.

     The flags argument for Sega Master System.
        bit 0 = Set column 0 to border color.
        bit 1 = Horizontal scrolling disabled on rows 0-1.
        bit 2 = Vertical scrolling disabled on columns 24-31.

     The flags argument for NES/Famicom.
        bit 0 = Background clipping (0 = hide left 8-pixel column, 1 = no clipping)
        bit 1 = Sprite clipping (0 = hide left 8-pixel column, 1 = no clipping)

  SCROLL x, y

     Sets the pixel scrolling for Sega Master System background.

     Sets the pixel scrolling for NES/Famicom background.

  PALETTE register, color
  PALETTE LOAD array_data_byte
  PALETTE LOAD VARPTR array_data_byte(0)

     For the Sega Master System:

     Sets a single palette register (0-31) to the color (0-63). Color bits are
     specified in a single byte as 00BBGGRR (two bits each for red, green, and
     blue).

     The registers 0-15 are for background tiles, and the registers 16-31 are
     for sprites. The tiles can request to use the sprite colors.

     Alternatively, you can load a full 32 entries palette using PALETTE LOAD.
     The array should be specified with DATA BYTE.

     For the NES/Famicom:

     Registers
        0-3 palette 0 for background tiles.
        4-7 palette 1 for background tiles.
        8-11 palette 2 for background tiles.
        12-15 palette 3 for background tiles.
        16-19 palette 0 for sprites 
        20-23 palette 1 for sprites 
        24-27 palette 2 for sprites 
        28-31 palette 3 for sprites 

     The value for each entry is in the range of 0-63 (the lower 4 bits choose
     the color, and bits 5-4 choose the luminance). The black color is any of
     the values $0e, $0f, $1e, $1f, $2e, $2f, $3e, or $3f. Don't use the value
     $0d as it generates a blacker than black signal that may cause unstable
     picture.

     Color table:
  
        0= White.      8= Lemon
        1= Dark blue.  9= Grass
        2= Blue.       A= Green
        3= Magenta.    B= Pear
        4= Purple.     C= Turquoise
        5= Wine.       D= Gray
        6= Red.        E= Black
        7= Golden.     F= Black

     For a reference of the palette colors see
     https://www.nesdev.org/wiki/PPU_palettes#2C02

     When you update the full palette the 32 bytes are written into the palette
     memory, and because how the NES/Famicom palette memory is implemented,
     the value at the offset 16 will be written over the offset 0 (the background
     color)

  MODE 0

     Select the video mode 0. In this mode, the 32x24 screen grid can have one
     of the 256 characters in each grid square.

     Each 8x8 pixel character can have a bitmap. Each line of a character
     can have two colors. For example, $f1 is a white foreground and black
     background.

           0 - Transparent.     8 - Red.
           1 - Black            9 - Light red.
           2 - Green            a - Yellow. 
           3 - Light green.     b - Pale yellow.
           4 - Dark blue.       c - Dark green.
           5 - Blue.            d - Purple.
           6 - Dark red.        e - Gray.  
           7 - Cyan.            f - White.

     For NES/Famicom, it simply clears the screen and erases the sprites.

  MODE 1

     Select the video mode 1. This is a high-resolution video mode where
     you can address each pixel individually.

     Useful for graphics artwork filling the screen. Notice there is no
     preloaded font for the screen, you should load individually the
     graphics needed at any time.

  MODE 2

     This video is pretty similar to MODE 0, except it is faster for defining
     bitmaps for the characters. Also, there is a limitation where the color for
     characters is limited to a foreground/background color for each 8 characters.

     VRAM addresses $2000-$201f contain the color for the characters group.

  MODE 4

     It is only available on Sega Master System, and it is the only mode supported
     in this console. VRAM $0000-$1fff are setup as background bitmaps, $2000-$37ff
     for sprites bitmaps, $3800-$3dff for the background patterns, and $3f00-$3fff
     for the sprites attributes. The unused portion $3e00-$3eff and $3f40-$3f7f 
     can be used for extra sprites (sprite numbers 120-123 and 125)

  SCREEN DISABLE

    Disables the video output. The current color of the border will fill the
    screen (can be set up using the BORDER statement). The video can be enabled
    again with SCREEN ENABLE or using a MODE statement.

    For NES/Famicom add a WAIT statement after this one because the operation
    is executed on the next video frame.

  SCREEN ENABLE

    Enables the video output (preserves the previous video mode set by MODE).

  SCREEN label[,origin_offset,target_offset,cols,rows]
  SCREEN label[,origin_offset,target_offset,cols,rows,origin_width]

    This statement is the fastest way to copy screen data to video. Using only
    "SCREEN label” copies a full screen of 32x24 characters to video.

    'label' points to a label inside your program containing the data for the
    screen, similar to this:
    
      my_screen:
         DATA BYTE "Top-left corner..." ' It continues...
        
    origin_offset is the offset inside the origin data.
    target_offset is the offset (0-767) inside the target video screen.
    cols is the horizontal size (number of columns) of your copy.
    rows is the vertical size (number of rows) of your copy.
    origin_width is the origin data width, useful to copy a sub-portion of a
                 big graphic screen, like a map, or when scrolling horizontally.
                 If this parameter is not used, the default value is the same
                 as "cols".
    
    This can serve to move large elements in video or to display beautiful 
    graphics screens.
    
    Label can be also a 8-bit array for dynamically drawn elements.
    
        DIM tile(4)
        
        SCREEN tile,0,0,2,2

    For the Sega Master System the source offset, target offset, and width are
    automatically multiplied by 2, because each character in the screen uses
    two bytes in VRAM. The first byte referring to the tile number (0-255), and
    the second byte specifies how it is used:

        bit 0 - Indicates to use tiles in the range 256-511
        bit 1 - Horizontal flip if set.
        bit 2 - Vertical flip if set.
        bit 3 - Uses sprite palette if set.
        bit 4 - The tile will be drawn on top of sprites.

  NAMETABLE number

    For NES/Famicom it selects the type of nametable arrangement. This is an
    informative field for emulators.

    0 - Vertical scrolling (CIRAM A10 = PPU A11)
    1 - Horizontal scrolling (CIRAM A10 = PPU A10)
    2 - Single-screen board (only with bank-switching)
    3 - 4-screen board (only with bank-switching)

  CHRRAM number

    For NES/Famicom bank-switching mode it allows to select the CHRRAM bank (0-3)

    The bit 2 (value 4) allows to select the PPU screen mirroring (0 for vertical
    scrolling, 1 for horizontal scrolling) See the UNROM 512 documentation.

  CHRROM number
  CHRROM number PATTERN number
  CHRROM PATTERN number

    For NES/Famicom the graphic data are saved into CHRROM banks of 8K.

    You should specify the CHRROM bank before putting any BITMAP statement.
    Currently only CHRROM 0 is supported for 32K ROM, and 0-3 for bank-switching
    ROM (UNROM 512)

    CVBasic will predefine an ASCII charset with color 3 in the patterns 32-127.

    You can choose the pattern number (0-511) for the following BITMAP statements.

  
  BITMAP "00000000"
  BITMAP "00001111"
  
  BITMAP "________"
  BITMAP "____XXXX"
  
    Allows you to draw using binary.

    For characters, you should use 8 BITMAP statements containing 8 pixels each
    to form a graphic definition.

    For sprites, you should use 16 BITMAP statements containing 16 pixels each.
    
    This is most useful when attaching a label and using it with DEFINE CHAR and
    DEFINE SPRITE.
    
    Characters taken as zero include: "0" "_" " " "."

    Every other character will be interpreted as one.

    For the Sega Master System, the sprites are composed by 8x16 pixels. If you
    use a 16x16 bitmap, it is automatically divided into 2 sprites of 8x16 pixels.
    The colors for each pixel are specified by using hexadecimal digits 1 to 9,
    and A to F.

    For the NES/Famicom, the sprites are composed by 8x16 pixels. The colors for
    each pixel are specified by the digits 1 to 3.

  PLAY SIMPLE
  PLAY SIMPLE NO DRUMS
  PLAY FULL
  PLAY FULL NO DRUMS
  
    Activates music player and selects the type of music played, SIMPLE only
    uses two channels, allowing the programmer to use SOUND 2 for sound effects
    (or SOUND 7 in MSX).
    
    FULL will use all three channels, so SOUND cannot be used in this context.
    
    The music player plays drums using the noise channel and the mix register.
    You can deactivate this feature using the NO DRUMS syntax, for example, if
    you want to generate explosion sounds with the noise channel, allowing you
    to use SOUND 3 (or SOUND 9 in MSX).

    Notice that the music player will update the sound channels on every video
    frame.


  PLAY NONE
  
    Deactivate the music player. Following this the programmer should turn off all
    the sound channels, using this code for Colecovision or SG1000:
    
      SOUND 0,,0
      SOUND 1,,0
      SOUND 2,,0
      SOUND 3,,0

    For MSX you need to do this:

      SOUND 5,,0
      SOUND 6,,0
      SOUND 7,,0
      SOUND 9,,$38

  PLAY label
  
    Plays the music pointed by 'label'.
    
    CVBasic will include automatically extra code for the music player.
    
    Music must be in this format: (each MUSIC statement can contain up to 4
    arguments)
    
        label:  DATA BYTE 8         ' Ticks per note (there are 50 ticks per second)
                MUSIC F4,A4#,C5
                MUSIC S,S,S
                MUSIC -,-,-

                MUSIC REPEAT
                MUSIC STOP

                MUSIC C4,F4,- ' Note how C4 extends along 4 tempos and F4 only 2
                MUSIC S,S,-
                MUSIC S,-,-
                MUSIC S,-,-
                
    Identifiers for notes: Note C, D, E, F, G, A, B followed by an octave (2-6), C7
                           is also available.

                           Optionally add the # sign for sharp.

                           Optionally add W, X, Y or Z to specify the instrument.
                           (W for piano, X for clarinet, Y for flute and Z for bass)
                           
                           Setting the instrument carries over in each channel for
                           MUSIC statements played afterward if the instrument
                           is not specified thereafter.
                           
                           Notice that the instrument waveforms can be altered
                           by modifying the cvbasic_epilogue.asm file for your
                           program.

                           Notice the bass instrument reduces two octaves your
                           current note, anything under octave 4 will be
                           silent with Colecovision SN76489 (not applies to
                           MSX AY-3-8910)

                           Also, the programmer can put S to sustain previous note,
                           or can put - for silence.
        
                           The fourth argument for MUSIC allows simple drums:

                             Valid values are:
                                -  none
                                M1 strong
                                M2 tap
                                M3 roll

    CVBasic will detect automatically PAL/NTSC Colecovision and will adjust 
    music timing and frequencies accordingly.

    If you are using bank-switching you can play music from a different bank
    (see BANK SELECT).

  PLAY OFF
  
    Stops music, if music is currently playing.
    

  DEF FN func = RANDOM % 10
  DEF FN screen_off(row, col) = (row * 32 + col)
  DEF FN resetsprite(number) = SPRITE number,$d1,0,0,0

    Allows to define functions with any number of arguments.
    
    Notice that these are processed like macros: The arguments are replaced
    as-is and the text of the function is inserted as-is after argument
    replacement. (because of that are included the extra parenthesis in the
    screen_off expression)

    For example, the two functions screen_off and resetsprite could be called as:
    
          A = func
          PRINT AT screen_off(4,8),"HELLO!"
          resetsprite(0)

    Please note that although it's possible to reuse internal function names,
    when called the internal functions have priority over DEF FN (DEF FN is
    ignored)

  INCLUDE "filename.bas"
  
    Includes the contents of another source file inside the current CVBasic
    program. 

    INCLUDE allows you to include external code anywhere in your program.
    You could even have half of a procedure in the main file and the rest of it
    in the included file.

    This is very useful for separating graphics and screen files.

  VDP(reg) = expr

    Sets the VDP register to the expression value.

    Not supported for NES/Famicom.

  CALL NAME       
   
    Calls assembly function NAME without arguments. Note CVBasic will put the
    NAME all in uppercase.

  CALL NAME(expr)  
  CALL NAME(expr,expr)  

    Calls assembly function NAME with one argument in HL (or Y,A for 6502)
    (Up to five arguments in Z80. HL, DE, BC, IX and IY).

  ASM code
  
    Allows you to insert assembly code code directly into your source code.
    The line content is copied directly to the output. It's also very useful
    to include assembly code modules, like this:
    
        ASM INCLUDE "yourfile.asm"

  BANK ROM 128
  BANK ROM 256
  BANK ROM 512
  BANK ROM 1024

    This statement allows you to use 128K-1024K cartridges for your program
    (Opcode's Megacart for the Colecovision, ASCII 16K mapper for MSX, SMS
    Sega Mapper for SG1000, and UNROM 512 for NES/Famicom).
    
    It should be the very first statement in your program. 128 allows for
    8 banks, 256 allows for 16 banks, 512 allows for 32 banks, and 1024 allows
    for 64 banks. Each bank measures 16 kilobytes.

    After this statement, your CVBasic program will continue at bank 0 (the
    global bank).

    In bank 0 you should have global procedures and data that are shared by
    all your banks.

    Note for NES/Famicom, you cannot refer to the top three banks (banks 13-15
    for 256K, and banks 29-31 for 512K) as these are used to save the CHRROM
    data.

  BANK 1-63

    Select the bank for the following code/data of your program. Each bank can
    contain up to 16319 bytes, and it is located in a separate area from the
    bank 0.

    Although you can use banks in any order, you cannot repeat bank numbers or
    use BANK 0 (this is done for you when using BANK ROM).

  BANK SELECT 1-63

    Selects a bank to access for the following statements. You can call
    procedures in the bank, or access data from the bank.

    BANK SELECT only can be used inside bank 0, otherwise, CVBasic will
    crash (like trying to change a carpet while standing over it).
        

>>>>>>>>>>>>>>  Expression syntax

The expression syntax is like a calculator.

The usual precedence rules apply to expression operators. Addition and
subtraction have lower precedence than multiplication and division. This means
1 + 2 * 3 = 7 not 9.

The expression parser will take advantage of 8-bit variables and numbers to optimize the code. If you want a variable to "become" 16-bit you need for example to add a 16-bit number to it.
  
  A=5               Decimal number (16 bits)
  A=5.              Decimal number (8 bits)
  A=$1000           Hexadecimal number
  A=&10101          Binary number
                    
  A="C"             ASCII code for letter (8 bits)
  A=B               Simple assignment
  A=A+B             Simple addition
  A=A-B             Simple subtraction
  A=A*B             Simple multiplication
                    Multiplication by 2/4/8/16/32/64/128/256 is
                    internally optimized.
  A=A/B             Simple unsigned division.
  A=A%B             Simple unsigned remainder.
  A=(A+B)-C
  A=A AND B
  A=A OR B          
  A=A XOR B
  A=NOT A
  A=-A
  A=A=B             If A and B are the same the result is $ffff (-1) else zero
  A=A<>B
  A=A<B
  A=A>B
  A=A<=B
  A=A>=B
  A=PEEK(expr)      Reads a memory location
                    PEEK always reads 8-bit data that can be processed in
                    an expression.
  A=VPEEK(expr)     Reads a VRAM memory location
                    VPEEK always reads 8-bit data that can be processed in
                    an expression. Not supported for NES/Famicom.
  A=ABS(expr)       Gets the absolute value of the expression (non-negative)
  A=SGN(expr)       Gets sign of expression (-1, 0 or 1)
  A=array(expr)     Accesses an array. The array can be defined with DIM or
                    label for DATA
  array(expr)=A     Writes data to an array. The array can be defined with DIM.
                    DATA is not writable

  A=USR NAME        Calls assembly function NAME (all in uppercase) without
                    arguments, and expects a result in HL.
  A=USR NAME(expr)  Calls assembly function NAME with one argument in HL, and
                    expects a result in HL (or Y,A for 6502).
  A=USR NAME(expr1,expr2) Calls assembly function NAME with one argument in HL
                    and the second one in DE (third would be BC, fourth would
                    be IX, and fifth would be IY). Only for Z80.

  #A=VARPTR B       Gets a pointer to a variable. Useful when linking assembler
                    routines.

  #A=VARPTR C(0)    Gets a pointer to an array. Can be defined with DIM or label
                    for DATA.

  CONT              Contains the state of both controllers.
  CONT.UP           Non-zero if any controller pointing up
  CONT.DOWN         Non-zero if any controller pointing down
  CONT.LEFT         Non-zero if any controller pointing left
  CONT.RIGHT        Non-zero if any controller pointing right
  CONT.BUTTON       Non-zero if any controller left button is pressed.
  CONT.BUTTON2      Non-zero if any controller right button is pressed.
  CONT.KEY          Current pressed key in any controller (0-9 for numbers,
                    10-*, 11-#, 15-Not pressed)

  CONT1             Contains the state of the first controller.
  CONT1.UP          Non-zero if controller pointing up
  CONT1.DOWN        Non-zero if controller pointing down
  CONT1.LEFT        Non-zero if controller pointing left
  CONT1.RIGHT       Non-zero if controller pointing right
  CONT1.BUTTON      Non-zero if the controller left button is pressed.
  CONT1.BUTTON2     Non-zero if the controller right button is pressed.
  CONT1.KEY         Current pressed key (0-9 for numbers, 10-*, 11-#, 15-Not pressed)

  CONT2             Contains the state of the second controller.
  CONT2.UP          Non-zero if controller pointing up
  CONT2.DOWN        Non-zero if controller pointing down
  CONT2.LEFT        Non-zero if controller pointing left
  CONT2.RIGHT       Non-zero if controller pointing right
  CONT2.BUTTON      Non-zero if the controller left button is pressed.
  CONT2.BUTTON2     Non-zero if the controller right button is pressed.
  CONT2.KEY         Current pressed key (0-9 for numbers, 10-*, 11-#, 15-Not pressed)

  RANDOM
    Produces a pseudo-random value between 0 and 65535.
    The value produced is different each time.
    
  RANDOM(range)
    Produces a pseudo-random value between 0 and range-1.
    The value produced is different each time.

  LEN(string)
    Returns the length of a string. Very useful in combination
    with DEF FN, for example, for creating strings centered on
    the screen.   

  POS(expr)
    Returns the current screen position (useful for PRINT AT)
    The expression is analyzed but no code is generated.

  INP(expr)
    Reads 8-bit data from the I/O port expr. Not available in 6502 targets.

  FRAME
    Returns the current frame number (0-65535, it cycles back to
    0 after reaching 65535)

  NTSC
    Returns 1 if the Colecovision is an NTSC console, otherwise
    returns zero.

  VDP.STATUS
    Returns the current status of the Video Display Processor. It is
    updated on each video frame.

  MUSIC.PLAYING
    Returns zero if music is not currently playing, returns a non-zero
    value otherwise.
    

>>>>>>>>>>>>>>  Useful VRAM addresses

Currently CVBasic handles in its own the bitmap, color and sprites tables.

However, you probably will need direct access to the screen.

The screen is a 32x24 grid located at the VRAM addresses  $1800-$1aff. It can be accessed using VPOKE (writing) and VPEEK (reading).

See the included example viboritas.bas for examples.

For Sega Master System the screen is a 32x28 grid located at the VRAM addresses $3800-$3dff. It can be accessed using VPOKE and VPEEK. SMS uses two bytes for each pattern to display on the screen, the first byte is the pattern number, and the second byte are flags. See the SCREEN statement for further details on the flags.


>>>>>>>>>>>>>>  Assembly language interfacing

The USR expression and the CALL statement allow you to call assembly language
modules from inside CVBasic programs. Note the label name for assembly
language modules is translated to uppercase.

CVBasic expect the following conventions to be preserved:

    Before calling:
    
    HL = Value of first argument (or trash)

    After calling:

    HL = Value from assembly language module (only USR expression)

If your module changes the address of the Stack Pointer (SP) then there is
a high probability that the CVBasic program will crash.

How your function should look:

    ASM MYFUNCTION:    
    ASM                ; ... your code...
    ASM                RET
    
    
>>>>>>>>>>>>>>  Some further notes

A program’s execution is sequential unless interrupted by GOTO or GOSUB. In any
of your programs, you should put GOTO at the end of the main block, otherwise
execution could run in undesirable ways. For example:

Example 1:

    A = 5
  stop:	GOTO stop	' Prevents CVBasic running out of ROM


Example 2:

    A = 5
  stop:   GOTO stop	' Prevents execution running inside procedure

  test:	PROCEDURE
		END
        
If you insert PROCEDURE, DATA, or MUSIC data in the middle of the
execution sequence, the Z80 processor will do strange things. So you
must put your data at the end of the program or where the execution doesn't
reach it.

Example 3:

    A = 6
    DATA 5,6,7      ' Bad, this gets executed! move it after the GOTO
  stop:    GOTO stop
        
By default, CVBasic programs can be so big as 32 kilobytes. The starting
address for Colecovision is $8000, MSX is $4000, and SG1000 is $0000.

You can measure your program by checking the generated LST file created by
the assembler.
         
     
>>>>>>>>>>>>>>  Permissions in Mac OS X and Linux

The provided executables for both Mac OS X and Linux probably will not have
the right permissions when uncompressed.

So is suggested to run these commands in your CVBasic directory:

  chmod 755 cvbasic
  chmod 755 cvbasic_linux

If your CVBasic directory is not in the current path you can run it using this
while at CVBasic directory:

  ./cvbasic game.bas game.asm


>>>>>>>>>>>>>>  Useful links

CoolCV emulator

  https://forums.atariage.com/topic/240800-coolcv-emulator-for-mac-os-x-linux-windows-and-raspberry/

  
>>>>>>>>>>>>>>  Acknowledgments

Thanks to following members of Atariage for contributing valuable suggestions:

  ARTRAG
  gemintronic
  Kiwi
  pixelboy
  visrealm
  youki
